﻿using LinqKit;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using OConf.Common;
using OConf.Entity;
using OConf.IBLL;
using OConf.Model;
using OConf.Model.Common;
using OConf.Model.RequestInput.ConfigInfo;
using OConf.Model.RequestInput.ProjectInfo;
using OConf.Service;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace OConf.BLL
{
    public class ProjectInfoBLL : IProjectInfoBLL
    {
        private readonly IConfiguration _configuration;
        private readonly ProjectInfoService _projectInfoService;
        private readonly ConfigInfoService _configInfoService;
        private readonly CNameSpaceService _cNameSpaceService;
        private readonly VersionsService _versionsService;
        private readonly ConfigInfoHistoryService _configInfoHistoryService;

        public ProjectInfoBLL(IConfiguration configuration)
        {
            _configuration = configuration;
            _projectInfoService = new ProjectInfoService(_configuration);
            _configInfoService = new ConfigInfoService(_configuration);
            _cNameSpaceService = new CNameSpaceService(_configuration);
            _versionsService = new VersionsService(configuration);
            _configInfoHistoryService = new ConfigInfoHistoryService(configuration);
        }

        /// <summary>
        /// 新增项目信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ReturnData<bool> AddProjectInfo(AddProjectInfoInput input)
        {
            try
            {
                if (_projectInfoService.IsExistsByProjectName(input.ProjectName))
                {
                    return ReturnDataHelper<bool>.Exists("项目名称已被使用", false);
                }

                ProjectInfoEntity projectInfo = new ProjectInfoEntity()
                {
                    ID = Guid.NewGuid().ToString(),
                    ProjectName = input.ProjectName,
                    ProjectDescription = input.ProjectDescription,
                    CreateTime = DateTime.Now,
                    IsDelete = false,
                    LastPublishTime = TimeCore.GetNowTimeOffset(),
                    IsProtect = input.IsProtect,
                    SecretKey = Guid.NewGuid().ToString("N")
                };

                if (_projectInfoService.AddEntity(projectInfo))
                {
                    return ReturnDataHelper<bool>.Success("操作成功", true);
                }
                else
                {
                    return ReturnDataHelper<bool>.Fail("操作失败", false);
                }
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteExceptionLog("AddProjectInfo,新增项目信息", ex);
                return ReturnDataHelper<bool>.Exception("系统异常", false);
            }
        }

        /// <summary>
        /// 编辑项目信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ReturnData<bool> EditProjectInfo(EditProjectInfoInput input)
        {
            try
            {
                if (!_projectInfoService.IsExists(input.ID))
                {
                    return ReturnDataHelper<bool>.NoExists("项目信息不存在", false);
                }
                ProjectInfoEntity projectInfo = new ProjectInfoEntity()
                {
                    ID = input.ID,
                    ProjectDescription = input.ProjectDescription,
                    IsProtect = input.IsProtect
                };
                if (_projectInfoService.UpdateEntity(projectInfo))
                {
                    return ReturnDataHelper<bool>.Success("操作成功", true);
                }
                else
                {
                    return ReturnDataHelper<bool>.Fail("操作失败", false);
                }
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteExceptionLog("EditProjectInfo,编辑项目信息", ex);
                return ReturnDataHelper<bool>.Exception("系统异常", false);
            }
        }

        /// <summary>
        /// 软删除项目信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ReturnData<bool> DeleteProjectInfo(DeleteProjectInfoInput input)
        {
            try
            {
                ProjectInfoEntity projectInfo = _projectInfoService.FindEnity(input.ID);
                if (projectInfo == null || projectInfo.IsDelete)
                {
                    return ReturnDataHelper<bool>.NoExists("项目信息不存在", false);
                }

                _projectInfoService.DeleteSoft(input.ID);

                //删除.json文件和redis缓存
                string fileDirPath = Path.Combine(GlobalValues.ConfigFileSaveDirPath, projectInfo.ProjectName);
                Directory.Delete(fileDirPath, true);

                return ReturnDataHelper<bool>.Success("操作成功", true);
            }
            catch (Exception ex)
            {
                //删除项目文件夹，文件夹不存在时返回成功
                if (ex is DirectoryNotFoundException)
                {
                    return ReturnDataHelper<bool>.Success("操作成功", true);
                }
                Log4NetHelper.WriteExceptionLog("DeleteProjectInfo,软删除项目信息", ex);
                return ReturnDataHelper<bool>.Exception("系统异常", false);
            }
        }

        /// <summary>
        /// 系统管理员回收站删除项目信息（硬删除）
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ReturnData<bool> SysDelete(DeleteProjectInfoInput input)
        {
            try
            {
                if (!_projectInfoService.IsExists(input.ID, true))
                {
                    return ReturnDataHelper<bool>.NoExists("项目信息不存在", false);
                }

                _projectInfoService.Delete(input.ID);
                return ReturnDataHelper<bool>.Success("操作成功", true);
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteExceptionLog("SysDelete,系统管理员回收站删除项目信息（硬删除）", ex);
                return ReturnDataHelper<bool>.Exception("系统异常", false);
            }
        }

        /// <summary>
        /// 还原项目信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ReturnData<bool> Reduction(DeleteProjectInfoInput input)
        {
            
            try
            {
                ProjectInfoEntity projectInfo = _projectInfoService.FindEnity(input.ID);
                if (projectInfo == null || !projectInfo.IsDelete)
                {
                    return ReturnDataHelper<bool>.NoExists("项目信息不存在", false);
                }

                _projectInfoService.Reduction(input.ID);//还原项目信息,更改删除标识

                CreateJsonFile(projectInfo);

                return ReturnDataHelper<bool>.Success("操作成功", true);
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteExceptionLog("Reduction,还原项目信息", ex);
                return ReturnDataHelper<bool>.Exception("系统异常", false);
            }
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="queryParam"></param>
        /// <returns></returns>
        public ReturnData<ReturnTableData<ProjectInfoModel>> QueryPage(QueryProjectInput queryParam)
        {
            ReturnTableData<ProjectInfoModel> result = new ReturnTableData<ProjectInfoModel>();
            ExpressionStarter<ProjectInfoEntity> where = PredicateBuilder.New<ProjectInfoEntity>(true);
            where = where.And(w => w.IsDelete == false);
            if (!string.IsNullOrEmpty(queryParam.ProjectName))
            {
                where = where.And(w => EF.Functions.Like(w.ProjectName, $"{queryParam.ProjectName}%"));
            }

            try
            {
                var info = _projectInfoService.QueryPage(queryParam.PageIndex, queryParam.PageSize, where);
                result.Total = info.Total;
                result.List = info.List.Select(w => new ProjectInfoModel()
                {
                    ID = w.ID,
                    ProjectName = w.ProjectName,
                    ProjectDescription = w.ProjectDescription,
                    CreateTime = w.CreateTime
                }).ToList();

                return ReturnDataHelper<ReturnTableData<ProjectInfoModel>>.Success("操作成功", result);
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteExceptionLog("QueryPage,分页查询", ex);
                return ReturnDataHelper<ReturnTableData<ProjectInfoModel>>.Exception("系统异常", null);
            }
        }

        /// <summary>
        /// 回收站项目信息列表
        /// </summary>
        /// <param name="queryParam"></param>
        /// <returns></returns>
        public ReturnData<ReturnTableData<ProjectInfoModel>> QueryRecycleProjectInfo(QueryProjectInput queryParam)
        {
            ReturnTableData<ProjectInfoModel> result = new ReturnTableData<ProjectInfoModel>();
            ExpressionStarter<ProjectInfoEntity> where = PredicateBuilder.New<ProjectInfoEntity>(true);
            where = where.And(w => w.IsDelete == true);
            if (!string.IsNullOrEmpty(queryParam.ProjectName))
            {
                where = where.And(w => w.ProjectName.StartsWith(queryParam.ProjectName));
            }

            try
            {
                var info = _projectInfoService.QueryPage(queryParam.PageIndex, queryParam.PageSize, where);
                result.Total = info.Total;
                result.List = info.List.Select(w => new ProjectInfoModel()
                {
                    ID = w.ID,
                    ProjectName = w.ProjectName,
                    ProjectDescription = w.ProjectDescription,
                    CreateTime = w.CreateTime
                }).ToList();
                return ReturnDataHelper<ReturnTableData<ProjectInfoModel>>.Success("操作成功", result);
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteExceptionLog("QueryRecycleProjectInfo,回收站项目信息列表", ex);
                return ReturnDataHelper<ReturnTableData<ProjectInfoModel>>.Exception("系统异常", null);
            }
        }

        /// <summary>
        /// 项目详情-包含的配置信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ReturnData<ProjectConfigs> GetProjectConfigs(GetProjectConfigsInput input)
        {
            try
            {
                ProjectInfoEntity projectInfo = _projectInfoService.FindEnity(input.ID);
                if (projectInfo == null)
                {
                    return ReturnDataHelper<ProjectConfigs>.NoExists("项目信息不存在", null);
                }
                ProjectConfigs result = new ProjectConfigs()
                {
                    ProjectID = projectInfo.ID,
                    ProjectName = projectInfo.ProjectName,
                    ProjectDescription = projectInfo.ProjectDescription,
                    IsProtect = projectInfo.IsProtect,
                    SecretKey = projectInfo.SecretKey
                };
                return ReturnDataHelper<ProjectConfigs>.Success("操作成功", result);
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteExceptionLog("GetProjectConfigs,项目详情-包含的配置信息", ex);
                return ReturnDataHelper<ProjectConfigs>.Exception("系统异常", null);
            }
        }

        /// <summary>
        /// 获取后台系统需要的配置信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ReturnData<BackProgramConfigInfo> GetBackProgramConfigInfo(BackProgramGetConfigInfoInput input)
        {
            try
            {
                ProjectInfoEntity projectInfo = _projectInfoService.FindEnityByProgramName(input.ProgramName);
                if (projectInfo == null || projectInfo.IsDelete)
                {
                    return ReturnDataHelper<BackProgramConfigInfo>.NoExists("项目信息不存在", null);
                }

                BackProgramConfigInfo result = GetConfigInfosFromJsonFile(projectInfo, input.NameSpaces);

                return ReturnDataHelper<BackProgramConfigInfo>.Success("操作成功", result);
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteExceptionLog("GetBackProgramConfigInfo,获取后台系统需要的配置信息", ex);
                return ReturnDataHelper<BackProgramConfigInfo>.Exception("系统异常", null);
            }
        }

        /// <summary>
        /// 检查配置信息版本
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ReturnData<BackProgramConfigInfo> CheckConfigInfo(CheckConfigInfoInput input)
        {
            try
            {
                ProjectInfoEntity projectInfo = _projectInfoService.FindEnityByProgramName(input.ProgramName);
                if (projectInfo == null || projectInfo.IsDelete)
                {
                    //项目信息已经被删除，通知客户端不要再发送请求
                    return ReturnDataHelper<BackProgramConfigInfo>.DiyResult((int)StatusCode.项目已删除, StatusCode.项目已删除.ToString(), null);
                }

                if (projectInfo.LastPublishTime <= input.LastPublishTime)
                {
                    return ReturnDataHelper<BackProgramConfigInfo>.DiyResult((int)StatusCode.配置信息已是最新, StatusCode.配置信息已是最新.ToString(), null);
                }

                BackProgramConfigInfo result = GetConfigInfosFromJsonFile(projectInfo, input.NameSpaces);

                return ReturnDataHelper<BackProgramConfigInfo>.Success("", result);
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteExceptionLog("CheckConfigInfo,检查配置信息版本", ex);
                return ReturnDataHelper<BackProgramConfigInfo>.Exception("系统异常", null);
            }
        }

        /// <summary>
        /// 生成json配置信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ReturnData<bool> GenerateConfigFileInfo(GenerateConfigInfoListInput input)
        {
            try
            {
                ProjectInfoEntity projectInfo = _projectInfoService.FindEnity(input.ProjectID);
                if (projectInfo == null)
                {
                    return ReturnDataHelper<bool>.NoExists("配置信息不存在", false);
                }

                CreateJsonFile(projectInfo);

                return ReturnDataHelper<bool>.Success("操作成功", true);
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteExceptionLog("GenerateConfigFileInfo,生成配置信息文件", ex);
                return ReturnDataHelper<bool>.Exception("系统异常", false);
            }
        }

        /// <summary>
        /// 生成项目json配置文件
        /// </summary>
        /// <param name="projectInfo"></param>
        /// <returns></returns>
        internal void CreateJsonFile(ProjectInfoEntity projectInfo)
        {
            List<CNameSpaceEntity> cNameSpaces = _cNameSpaceService.GetList(projectInfo.ID, true);
            foreach (var cNameSpace in cNameSpaces)
            {
                CreateJsonFile(projectInfo, cNameSpace);
            }
        }

        /// <summary>
        /// 按NameSpace生成配置文件
        /// </summary>
        /// <param name="projectInfo"></param>
        /// <param name="cNameSpace"></param>
        /// <returns></returns>
        internal bool CreateJsonFile(ProjectInfoEntity projectInfo, CNameSpaceEntity cNameSpace)
        {
            var version = _versionsService.GetLatestVersion(projectInfo.ID, cNameSpace.ID);
            if (version == null)
            {
                return false;
            }

            var configInfos = _configInfoHistoryService.GetListByVersionId(version.ID);
            Dictionary<string, string> dic = new Dictionary<string, string>();
            foreach (var item in configInfos)
            {
                dic.Add($"{cNameSpace.NameSpace}:{item.ConfigKey}", item.ConfigValue);
            }

            //将配置信息保存到json文件中
            string fileDirPath = Path.Combine(GlobalValues.ConfigFileSaveDirPath, projectInfo.ProjectName);
            FileCore.CreateDirectory(fileDirPath);

            FileCore.SaveFile(Path.Combine(fileDirPath, $"{cNameSpace.NameSpace}.json"), JsonConvert.SerializeObject(dic));

            return true;
        }

        /// <summary>
        /// 获取配置文件信息
        /// </summary>
        /// <param name="projectName"></param>
        /// <param name="nameSpace"></param>
        /// <returns></returns>
        internal static string GetJsonFile(string projectName, string nameSpace)
        {
            string fileDirPath = Path.Combine(GlobalValues.ConfigFileSaveDirPath, projectName);
            if (!Directory.Exists(fileDirPath))
            {
                return string.Empty;
            }

            string filePath = Path.Combine(fileDirPath, $"{nameSpace}.json");
            if (!File.Exists(filePath))
            {
                return string.Empty;
            }

            return File.ReadAllText(filePath);
        }

        /// <summary>
        /// 从json文件中获取命名空间下的配置信息
        /// 项目发布、配置回滚时获取配置信息
        /// </summary>
        /// <param name="projectName"></param>
        /// <param name="nameSpace"></param>
        /// <param name="publishTime"></param>
        /// <returns></returns>
        internal static BackProgramConfigInfo GetConfigInfoFromJsonFile(string projectName, string nameSpace, long publishTime)
        {
            string jsonStr = GetJsonFile(projectName, nameSpace);
            if (string.IsNullOrEmpty(jsonStr))
            {
                return null;
            }

            Dictionary<string, string> dic = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonStr);

            List<ConfigInfo> configs = dic.Select(w => new ConfigInfo()
            {
                Key = w.Key,
                Value = w.Value
            }).ToList();

            List<BackCNameSpaceModel> cNameSpaceModel = new List<BackCNameSpaceModel>()
            {
                new BackCNameSpaceModel()
                {
                    NameSpace = nameSpace,
                    ConfigInfos = configs
                }
            };

            BackProgramConfigInfo result = new BackProgramConfigInfo()
            {
                ProjectName = projectName,
                LastPublishTime = publishTime,
                NameSpaces = cNameSpaceModel
            };

            return result;
        }

        /// <summary>
        /// 从json文件中获取命名空间下的配置信息
        /// 后端接口获取配置信息时使用
        /// </summary>
        /// <param name="projectInfo"></param>
        /// <param name="incNameSpaces"></param>
        /// <returns></returns>
        internal BackProgramConfigInfo GetConfigInfosFromJsonFile(ProjectInfoEntity projectInfo, List<string> incNameSpaces)
        {
            BackProgramConfigInfo result = new BackProgramConfigInfo()
            {
                ProjectName = projectInfo.ProjectName,
                LastPublishTime = projectInfo.LastPublishTime,
                NameSpaces = new List<BackCNameSpaceModel>()
            };

            //从配置文件中获取配置信息（获取的配置信息是已发布）
            var nameSpaces = _cNameSpaceService.GetList(projectInfo.ID).Where(w => incNameSpaces.Any(n => n == w.NameSpace)).ToList();
            foreach (var item in nameSpaces)
            {
                BackCNameSpaceModel nameSpaceModel = new BackCNameSpaceModel()
                {
                    NameSpace = item.NameSpace,
                    ConfigInfos = new List<ConfigInfo>()
                };

                string jsonStr = GetJsonFile(projectInfo.ProjectName, item.NameSpace);
                if (string.IsNullOrEmpty(jsonStr))
                {
                    //如果配置文件不存在，则生成配置文件
                    CreateJsonFile(projectInfo, item);
                    jsonStr = GetJsonFile(projectInfo.ProjectName, item.NameSpace);

                    if (string.IsNullOrEmpty(jsonStr))
                    {
                        continue;
                    }
                }

                Dictionary<string, string> dic = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonStr);
                foreach (var dicItem in dic)
                {
                    nameSpaceModel.ConfigInfos.Add(new ConfigInfo()
                    {
                        Key = dicItem.Key,
                        Value = dicItem.Value
                    });
                }

                result.NameSpaces.Add(nameSpaceModel);
            }

            return result;
        }

        /// <summary>
        /// 重置秘钥
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public ReturnData<bool> ResetSecretKey(ResetSecretKeyInput input)
        {
            try
            {
                if (!_projectInfoService.IsExists(input.ID))
                {
                    return ReturnDataHelper<bool>.NoExists("项目信息不存在", false);
                }

                string newSecretKey = Guid.NewGuid().ToString("N");

                //重置秘钥，自动启用保护状态
                _projectInfoService.ModifySecretKey(input.ID, newSecretKey);

                return ReturnDataHelper<bool>.Success("操作成功", true);
            }
            catch (Exception ex)
            {
                Log4NetHelper.WriteExceptionLog("ResetSecretKey,重置秘钥", ex);
                return ReturnDataHelper<bool>.Exception("系统异常", false);
            }
        }
    }
}